// AST语法树 vnode
/**
 * {
 *   tag: 'div',
 *   attrs: [{id: "app"}]
 *   children: [
 *     {
 *       tag: null
 *       text: 'hello'
 *     },
 *     {
 *        tag: 'p'
 *     }
 *   ]
 * }
 */

// 匹配标签名称
const ncname =`[a-zA-Z_][\\-\\.0-9_a-zA-Z]*`;
// 匹配特殊标签，比如：/<span:xx>
const qnamecapture= `((?:${ncname}\\:)?${ncname})`; 
// 标签开头的正则 捕获的内容是标签名
const startTagOpen = new RegExp(`^<${qnamecapture}`);
// 匹配标签结尾的</div>
const endTag = new RegExp(`^<\\/${qnamecapture}[^>]*>`);
// 匹配标签属性
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/;
// 匹配标签结束的 >
const startTagClose=/^\s*(\/?)>/;
// 匹配模版语法{{}}
const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g


// 创建AST语法树
function createASTElement (tag, attrs) {
  return {
    tag,
    attrs,
    children: [],
    type: 1,
    parent: null
  }
}

// 根元素
let root;
// 当前元素的父节点
let createParent;
// 数据结构 栈
let stack = [];

// 遍历开始标签
function start(tag, attrs) {
  let element = createASTElement(tag, attrs);
  if (!root) {
    root = element;
  }

  createParent = element;
  stack.push(element);
}

// 获取文本
function charts (text) {
  // text = text.replace(/\s/g, '')
  if (text) {
    createParent.children.push({
      type: 3,
      text
    })
  }
}

// 遍历结束标签
function end (tag) {
  let element = stack.pop();
  createParent = stack[stack.length - 1];

  if (createParent) {
    element.parent = createParent.tag
    createParent.children.push(element);
  }
}

// 

// 遍历
export function parseHTML (html) {
  while (html) {
    // 开始标签
    let textEnd = html.indexOf('<');
    if (textEnd === 0) {
      // 获取开始标签的内容
      const startTagMatch = parseStartTag()
      if (startTagMatch) {
        start(startTagMatch.tagName, startTagMatch.attrs);
        continue;
      }
      
      // 结束标签
      let endTagMatch = html.match(endTag)
      if (endTagMatch) {
        advance(endTagMatch[0].length)
        end(endTagMatch[1]) 
      }
      continue;
    }

    // 获取文本
    if (textEnd > 0) {
      let text = html.slice(0, textEnd);

      if (text) {
        advance(text.length);
        charts(text);
      }
    }

  }

  function parseStartTag () {
    const start = html.match(startTagOpen);

    if (!start) {
      return false;
    }

    // 创建AST语法树
    let match = {
      tagName: start[1],
      attrs: []
    }

    // 删除开始标签
    advance(start[0].length)

    // 获取属性，属性有多个，需要进行遍历
    // 需要注意 > 结束标签
    let attr;
    let end;
    while (!(end = html.match(startTagClose)) && (attr = html.match(attribute))) {
      match.attrs.push({
        name: attr[1],
        value: (attr[3] || attr[4] || attr[5]).replace(/\s/g, '')
      })
      advance(attr[0].length)
      // break;
    }

    if (end) {
      advance(end[0].length);
      return match;
    }
  }

  function advance (n) {
    html = html.substring(n)
  }

  return root;
}